/*
 * string_test.c
 *
 *  Created on: Aug 31, 2008
 *      Author: V
 */

#include "../string/String.h"

#include "CuTest.h"

#include "../gc6.7/include/gc.h"

#include <assert.h>


void TestString_new_NullInputOK(CuTest* ct)
{
	pString string = String_new(NULL);
	CuAssertStrEquals(ct, "\0", string->cString);
}


void TestString_new_CStringInputOK(CuTest* ct)
{
	const char* input = "Hello World!";
	pString string = String_new(input);
	CuAssertStrEquals(ct, input, string->cString);
}


void TestString_new_MultilineInputOK(CuTest* ct)
{
	const char* input = "Hello World\n!\r!";
	pString string = String_new(input);
	CuAssertStrEquals(ct, input, string->cString);
}


void TestString_indexOf_NotFoundReturnsMinusOne(CuTest* ct)
{
	pString string = String_new("Gaoeiuiuedsthhsnthsnt");
	const char* delims = "kx"; // not in
	CuAssertIntEquals(ct, -1, String_indexOf(string, delims));
}


void TestString_indexOf_EndingCharacterOK(CuTest* ct)
{
	pString string = String_new("abcdefghijklmnopqrstuvwxyz");
	CuAssertIntEquals(ct, 25, String_indexOf(string, "z"));
}


void TestString_indexOf_StartingCharacterOK(CuTest* ct)
{
	pString string = String_new("abcdefghijklmnopqrstuvwxyz");
	CuAssertIntEquals(ct, 0, String_indexOf(string, "a"));
}


void TestString_resize_SizingUpWorks(CuTest* ct)
{
	pString string = String_new("abc");
	CuAssertIntEquals(ct, 3, string->length);
	CuAssertStrEquals(ct, "abc", string->cString);

	string = String_resize(string, 20);
	CuAssertIntEquals(ct, 20, string->length);
	CuAssertStrEquals(ct, "abc", string->cString);
}


void TestString_resize_SizingDownWorks(CuTest* ct)
{
	pString string = String_new("123456789");
	string = String_resize(string, 5);
	CuAssertIntEquals(ct, 5, string->length);
	CuAssertStrEquals(ct, "12345", string->cString);
}


void TestString_resize_SideSizingWorks(CuTest* ct)
{
	pString string = String_new("abcde");
	pString string2 = String_resize(string, 5);
	CuAssert(ct, "String_resize returns different string", string != string2);
	CuAssertStrEquals(ct, string->cString, string2->cString);
	CuAssertIntEquals(ct, string->length, string2->length);
}


void TestString_substring(CuTest* ct)
{
	pString string = String_new("abcdefg");
	pString substring = String_substring(string, 1, 3);
	CuAssertIntEquals(ct, 2, substring->length);
	CuAssertStrEquals(ct, "bc", substring->cString);
}


void TestString_substring_CopyUntilEndWorks(CuTest* ct)
{
	pString string = String_new("abcdefghijk");
	CuAssertIntEquals(ct, 11, string->length);
	pString substring = String_substring(string, 3, 0);
	//String_substring = String_new("thingie");
	CuAssertStrEquals(ct, "defghijk", substring->cString);

	substring = String_substring(string, 0, 0); // copy all
	CuAssertStrEquals(ct, string->cString, substring->cString);
}

void TestString_substring_CopyLastNullWorks(CuTest* ct)
{
	pString string = String_new("abcdefghijk");
	int index = String_indexOf(string, "k");
	pString substring = String_substring(string, index, 0);
	CuAssertStrEquals(ct, "k", substring->cString);
	CuAssertIntEquals(ct, 1, substring->length);

	substring = String_substring(substring, 1, 0);
	CuAssertTrue(ct, substring != NULL);
	CuAssertStrEquals(ct, "\0", substring->cString);


	substring = String_substring(substring, 0, 0); // copy all
	CuAssertStrEquals(ct, "\0", substring->cString);
}

void TestString_substring_NegativeStartWorks(CuTest* ct)
{
	pString input = String_new("0123456789");
	pString result = String_substring(input, -1, 0);
	assert(result != NULL);
	CuAssertStrEquals(ct, "9\0", result->cString);

	result = String_substring(input, -20, 0);
	assert(result != NULL);
	CuAssertStrEquals(ct, input->cString, result->cString);

	CuAssertStrEquals(ct, "\n", String_substring(String_new("aoeu\n"), -1, 0)->cString);
}

void TestString_head_DoesNotCrashOnNull(CuTest* tc)
{
	pString string = String_head(0, 0);
	CuAssert(tc, "NULL to String_head produces NULL.", string == NULL);
}

void TestString_head_Head1UnixWorks(CuTest* tc)
{
	pString input = String_new("1\n2");
	pString ret = String_head(input, 1);
	CuAssertStrEquals(tc, "1", ret->cString);
}

void TestString_head_Head2UnixWorks(CuTest* ct)
{
	pString input = String_new("1\n2\n3\n4\n551525354");
	pString ret = String_head(input, 2);
	CuAssertStrEquals(ct, "1\n2", ret->cString);
}

void TestString_head_Head2WithTrailingSlashNs(CuTest* ct)
{
	pString input = String_new("1\n2\n3\n4\n551525354\n\n");
	pString ret = String_head(input, 2);
	CuAssertStrEquals(ct, "1\n2", ret->cString);
}

void TestString_head_Head2WindowsWorks(CuTest* ct)
{
	pString input = String_new("1\r\n2\r\n3\r\n4\r\n551525354\r\n\r\n");
	pString ret = String_head(input, 2);
	CuAssertStrEquals(ct, "1\n2", ret->cString);
}

void TestString_head_NegativeHeadWorks(CuTest* ct)
{
	pString input = String_new("1\r\n2\r\n3\r\n4\r\n5");
	pString ret = String_head(input, -2);
	CuAssertStrEquals(ct, "1\r\n2\r\n3\r\n", ret->cString);
}

void TestString_trim(CuTest* ct)
{
	pString input = String_new("base");
	pString result = String_trim(input);
	assert(result != NULL);
	CuAssertStrEquals(ct, input->cString, result->cString);

	input = String_new("\t\t\rbase\r\n ");
	result = String_trim(input);
	assert(result != NULL);
	CuAssertStrEquals(ct, "base", result->cString);

	input = String_new("C.txt\r\r\n");
	result = String_trim(input);
	assert(result != NULL);
	CuAssertStrEquals(ct, "C.txt", result->cString);
}

void TestString_concat(CuTest* ct)
{
	pString first = String_new("abc");
	pString second = String_new("def");
	pString concated = String_concat(first, second);
	CuAssertStrEquals(ct, "abcdef", concated->cString);

	first = String_new(NULL);
	concated = String_concat(first, second);
	CuAssertStrEquals(ct, "def", concated->cString);

	first = second;
	second = String_new(NULL);
	concated = String_concat(first, second);
	CuAssertStrEquals(ct, "def", concated->cString);

}

void TestString_lineCount(CuTest* ct)
{
	pString string = String_new("1\n\n\n\n\n"); // 6 lines
	CuAssertIntEquals(ct, 6, String_lineCount(string));

	string = String_new("\n");
	CuAssertIntEquals(ct, 2, String_lineCount(string));

	string = String_new("1\r\n2\r\n3\r\n4");
	CuAssertIntEquals(ct, 4, String_lineCount(string));
}

void TestString_popLineGetLine(CuTest* ct)
{
	pString input = String_new("a\nb\nc");
	pString result = String_popLineGetLine(input);
	CuAssertIntEquals(ct, 2, result->length);
	CuAssertStrEquals(ct, "a\n", result->cString);

	input = String_new("abcdef\naueodi,.P\n@%#$<YOEU");
	result = String_popLineGetLine(input);
	CuAssertStrEquals(ct, "abcdef\n", result->cString);

	input = String_new("abc\r\nxoeu,,oaeup\r\nHello  Hurld\r\n\t");
	result = String_popLineGetLine(input);
	CuAssertStrEquals(ct, "abc\r\n", result->cString);

	input = String_new("\n");
	result = String_popLineGetLine(input);
	CuAssertStrEquals(ct, "\n\0", result->cString);

	input = String_new("1\r\n2\r\n3\r\n4\r\n5");
	result = String_popLineGetLine(input);
	CuAssertStrEquals(ct, "1\r\n\0", result->cString);
}

void TestString_popLineGetStack(CuTest* ct)
{
	pString input = String_new("a\nb\nc");
	pString result = String_popLineGetStack(input);
	CuAssertIntEquals(ct, 3, result->length);
	CuAssertStrEquals(ct, "b\nc", result->cString);

	input = String_new("abcdef\naueodi,.P\n@%#$<YOEU");
	result = String_popLineGetStack(input);
	CuAssertStrEquals(ct, "aueodi,.P\n@%#$<YOEU", result->cString);

	input = String_new("abc\r\nxoeu,,oaeup\r\nHello  Hurld\r\n\t");
	result = String_popLineGetLine(input);
	CuAssertStrEquals(ct, "abc\r\n", result->cString);

	input = String_new("\n");
	result = String_popLineGetStack(input);
	CuAssertStrEquals(ct, "\0", result->cString);

	input = String_new("1\r\n2\r\n3\r\n4\r\n5");
	result = String_popLineGetStack(input);
	CuAssertStrEquals(ct, "2\r\n3\r\n4\r\n5\0", result->cString);
}

void TestString_appendLine(CuTest* ct)
{
	pString base = String_new("1");
	pString append = String_new("2");
	pString result = String_appendLine(base, append);
	assert(result != NULL);
	CuAssertStrEquals(ct, "1\n2\n", result->cString);

	base = String_new("1\n");
	append = String_new("2\n");
	result = String_appendLine(base, append);
	CuAssertStrEquals(ct, "1\n2\n", result->cString);

	base = String_new("1\r\n");
	append = String_new("2\r\n");
	result = String_appendLine(base, append);
	CuAssertStrEquals(ct, "1\r\n2\r\n", result->cString);

	base = String_new(NULL);
	append = String_new("1\r\n");
	result = String_appendLine(base, append);
	CuAssertStrEquals(ct, "1\r\n", result->cString);
}

void TestString_equals(CuTest* ct)
{
	pString first = String_new("a");
	pString second = String_new("a");
	strcmp(first->cString, second->cString);
	CuAssertIntEquals(ct, 1, String_equals(first, second));

	first = String_new("\n");
	second = String_substring(String_new("aoeu\n"), -1, 0);
	second = String_new("\n");
	CuAssertStrEquals(ct, "\n", first->cString);
	CuAssertStrEquals(ct, "\n", second->cString);
	CuAssertIntEquals(ct, 1, String_equals(first, second));
}
